package com.bamboo.ossservice.config;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.*;
import com.bamboo.servicebase.exceptionhandler.BambooException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * @author jack.wu
 * @version 1.0
 * @date 2020-07-04
 */
@Slf4j
@Component
public class OssUtil {

    @Value("${aliyun.oss.file.endpoint}")
    private String endPoint;

    @Value("${aliyun.oss.file.keyid}")
    private String keyId;

    @Value("${aliyun.oss.file.keysecret}")
    private String keySecret;

    @Value("${aliyun.oss.file.bucketname}")
    private String bucketName;


    public static String END_POINT;
    public static String ACCESS_KEY_ID;
    public static String ACCESS_KEY_SECRET;
    public static String BUCKET_NAME;

    @PostConstruct
    public void init() {
        BUCKET_NAME = bucketName;
        ACCESS_KEY_ID = keyId;
        END_POINT = endPoint;
        ACCESS_KEY_SECRET = keySecret;
    }


    private static OSSClient getOssClient() {
        return new OSSClient(END_POINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
    }

    /**
     * 上传文件
     *
     * @param file           文件
     * @param folderPath 要存放的文件夹路径，即阿里云的ObjectName
     * @return url
     */
    public static String uploadFile(MultipartFile file, String folderPath) {

        // 随机生成的文件名
        String newName;
        OSSClient client = getOssClient();
        String bucketName = BUCKET_NAME;
        InputStream inputStream;
        try {
            if (file != null && !file.isEmpty()) {
                newName = UUID.randomUUID().toString().replaceAll("-", "") + file.getOriginalFilename();
                inputStream = file.getInputStream();
                client.putObject(bucketName, folderPath + newName, inputStream);
                return "https://" + bucketName + "." + END_POINT + "/" + folderPath + newName;
            }
            return null;
        } catch (Exception e) {
            log.error("*********阿里云OSS上传文件出错*********");
            throw new BambooException();
        } finally {
            try {
                client.shutdown();
            } catch (Exception e) {
                log.error("*********关闭阿里云连接（OSSClient）出错了*********");
            }

        }
    }

    /**
     * 删除文件
     *
     * @param imageLocation 图片在阿里云的完整路径，如：epc/mazda/part/aaa.jp      
     */
    public static void deleteFile(String imageLocation) {
        OSSClient client = getOssClient();
        try {
            String bucketName = BUCKET_NAME;
            client.deleteObject(bucketName, imageLocation);
        } catch (Exception e) {
            log.error("*********阿里云OSSs删除文件出错*********");
            throw new BambooException();
        } finally {
            try {
                client.shutdown();
            } catch (Exception e) {
                log.error("*********关闭阿里云连接（OSSClient）出错了*********");
            }
        }
    }


    /**
     * 下载文件
     *    
     */
    public static void downloadFile(String bucketName, String objectKey, String filename) {
        OSSClient client = getOssClient();
        try {
            ObjectMetadata t = client.getObject(new GetObjectRequest(bucketName, objectKey), new File(filename));

        } catch (Exception e) {
            log.error("*********阿里云OSSs下载文件出错*********");
            throw new BambooException();
        } finally {
            client.shutdown();
        }
    }


    /**
     * 获取某个Object
     */
    public static InputStream getObject(String objectName) {
        OSSClient client = getOssClient();
        InputStream objectContent;
        try {
            OSSObject object = client.getObject(BUCKET_NAME, objectName);
            objectContent = object.getObjectContent();
            return objectContent;
        } catch (Exception e) {
            log.error("*********阿里云OSSs下载文件出错*********");
            throw new BambooException();
        } finally {
            try {
                client.shutdown();
            } catch (Exception e) {
                log.error("*********关闭阿里云连接（OSSClient）出错了！*********");
            }

        }

    }

    /**
     * 分片上传MultipartUpload
     */
    public String uploadFile(String resourceHost, String key, MultipartFile partFile) throws IOException {
        OSSClient client = getOssClient();
        return multipartUpload(key, partFile, client, resourceHost);

    }

    private String multipartUpload(String key, MultipartFile partFile, OSSClient client, String bucketName) throws IOException {

        // 开始Multipart Upload
        InitiateMultipartUploadRequest initiateMultipartUploadRequest = new InitiateMultipartUploadRequest(bucketName, key);
        InitiateMultipartUploadResult initiateMultipartUploadResult = client.initiateMultipartUpload(initiateMultipartUploadRequest);
        final int partSize = 1024 * 1024 * 5;

        // 计算分块数目
        int partCount = (int) (partFile.getSize() / partSize);

        if (partFile.getSize() % partSize != 0) {
            partCount++;
        }

        // 新建一个List保存每个分块上传后的ETag和PartNumber
        List<PartETag> tags = new ArrayList<>();
        for (int i = 0; i < partCount; i++) {
            // 获取文件流
            InputStream fis = partFile.getInputStream();
            // 跳到每个分块的开头
            long skipBytes = (long) partSize * i;
            fis.skip(skipBytes);
            // 计算每个分块的大小
            long size = partSize < partFile.getSize() - skipBytes ? partSize :
                    partFile.getSize() - skipBytes;
            // 创建UploadPartRequest，上传分块
            UploadPartRequest uploadPartRequest = new UploadPartRequest();
            uploadPartRequest.setBucketName(bucketName);
            uploadPartRequest.setKey(key);
            uploadPartRequest.setUploadId(initiateMultipartUploadResult.getUploadId());
            uploadPartRequest.setInputStream(fis);
            uploadPartRequest.setPartSize(size);
            uploadPartRequest.setPartNumber(i + 1);
            UploadPartResult uploadPartResult = client.uploadPart(uploadPartRequest);
            // 将返回的PartETag保存到List中。
            tags.add(uploadPartResult.getPartETag());
            // 关闭文件
            fis.close();
        }
        CompleteMultipartUploadRequest completeMultipartUploadRequest =
                new CompleteMultipartUploadRequest(bucketName, key, initiateMultipartUploadResult.getUploadId(), tags);
        // 完成分块上传
        CompleteMultipartUploadResult completeMultipartUploadResult =
                client.completeMultipartUpload(completeMultipartUploadRequest);
        return completeMultipartUploadResult.getKey();

    }


}
